using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Resources;
using System.Globalization;

namespace Media_Renamer {
    public partial class MainForm : LocalizedForm {
        private bool _cancelOperation = false;
        
        public MainForm() {
            InitializeComponent();
            mediaLibrary.ItemContextMenuStrip = itemMenu;
            setUpCulture();
            //CustomDialogResult result = CustomMessageBox.Show(string.Format("The file {0} already exists.Do you want to overwrite it?", "C:\\prueba"), "Copy Error", CustomMessageBoxButtons.YesYesToAllNoNoToAllCancel);
            /*
            CustomMessageBox.Show("Test");
            CustomMessageBox.Show("Test", "Titulo");
            CustomMessageBox.Show("Test", "Titulo", CustomMessageBoxButtons.OKOnly);
            CustomMessageBox.Show("Test", "Titulo", CustomMessageBoxButtons.AbortRetryIgnore);
            CustomMessageBox.Show("Test", "Titulo", CustomMessageBoxButtons.OKCancel);
            CustomMessageBox.Show("Test", "Titulo", CustomMessageBoxButtons.RetryCancel);
            CustomMessageBox.Show("Test", "Titulo", CustomMessageBoxButtons.YesNo);
            CustomMessageBox.Show("Test", "Titulo", CustomMessageBoxButtons.YesYesToAllNoNoToAll);
            CustomMessageBox.Show("Test", "Titulo", CustomMessageBoxButtons.YesYesToAllNoNoToAllCancel);
            CustomMessageBox.Show("Test", "Titulo", CustomMessageBoxButtons.YesNoCancel, MessageBoxIcon.Information, CustomMessageBoxDefaultButton.Yes, MessageBoxOptions.ServiceNotification);
             * */
        }
        override public void setUpCulture() {
            this.lblDestinationFormatter.Text = this.getString("mainForm.formatter.destinationTitle");
            this.lblFilenameFormatter.Text = this.getString("mainForm.formatter.filenameTitle");
            this.lblHelpFormatter.Text = this.getString("mainForm.formatter.help");
            this.toolFormat.Text = this.getString("mainForm.tool.toggleFormatter");
            this.toolRefresh.Text = this.getString("mainForm.tool.refresh");
            this.toolCopyAndFormat.Text = this.getString("mainForm.tool.formatAndCopy");
            this.toolFormat.Text = this.getString("mainForm.tool.format");
            this.toolAddFile.Text = this.getString("mainForm.tool.addFile");
            this.toolAddFolder.Text = this.getString("mainForm.tool.addFolder");
            this.toolFormatter.Text = this.getString("mainForm.tool.toggleFormatter");
            this.toolEmpty.Text = this.getString("mainForm.tool.empty");
            this.menuHelp.Text = this.getString("mainForm.menu.help");
            this.menuContentHelp.Text = this.getString("mainForm.menu.help.contents");
            this.menuHelpFormat.Text = this.getString("mainForm.menu.help.contents.format");
            this.menuAbout.Text = this.getString("mainForm.menu.help.about");
            this.menuFile.Text = this.getString("mainForm.menu.file");
            this.menuAddFile.Text = this.getString("mainForm.menu.file.addFile");
            this.menuAddFolder.Text = this.getString("mainForm.menu.file.addFolder");
            this.menuExit.Text = this.getString("mainForm.menu.file.exit");
            this.statusCancel.Text = this.getString("mainForm.status.statusCancel");

            this.itemMenu_Edit.Text = this.getString("mainForm.mediaLibrary.item.menu.edit");
            this.itemMenu_Info.Text = this.getString("mainForm.mediaLibrary.item.menu.info");
        }

        #region Eventos 

        private void mediaLibrary1_Load(object sender, EventArgs e) {
            Formatter_Click(null, null);
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
            HelpDialog dlgHelp = new HelpDialog();
            dlgHelp.Show();
        }

        private void toolCancel_Click(object sender, EventArgs e) {
            cancelOperation();
        }

        private void helpFormat_Click(object sender, EventArgs e) {
            HelpDialog dlgHelp = new HelpDialog();
            dlgHelp.Show();
        }

        private void Formatter_Click(object sender, EventArgs e) {
            pnlFormat.Visible = this.toolFormatter.Checked;
            Properties.Settings.Default.showFormatter = this.toolFormatter.Checked;
            saveSettings();
        }

        private void addFile_Click(object sender, EventArgs e) {
            addFile();
        }

        private void addFolder_Click(object sender, EventArgs e) {
            addFolder();
        }

        private void toolRefresh_Click(object sender, EventArgs e) {
            mediaLibrary.refreshLibrary();
        }

        private void AnyFormatterTextbox_FocusLeave(object sender, EventArgs e)  {
            saveSettings();
        }

        private void AnyFormatterTextbox_KeyDown(object sender, KeyEventArgs e) {
            saveSettings();
        }

        private void toolFormat_Click(object sender, EventArgs e) {
            foreach (MP3File mediaFile in mediaLibrary.selectedFiles()) {
                string finalFormat = formatFilename(mediaFile, this.formatterTextbox.Text);
                System.IO.FileInfo file = new System.IO.FileInfo(mediaFile.filePath);
                String oldFilepath = mediaFile.filePath;
                file.MoveTo(file.Directory.FullName + System.IO.Path.DirectorySeparatorChar + finalFormat);
                mediaLibrary.Updating = true;
                int oldIndex = mediaLibrary.getRow(oldFilepath).Index;
                String finalPath = file.Directory.FullName + System.IO.Path.DirectorySeparatorChar + finalFormat;
                if (finalPath.ToLower() != oldFilepath.ToLower()) {
                    mediaLibrary.addFile(finalPath, oldIndex).Selected = true;
                    mediaLibrary.removeFile(oldFilepath);
                }
                mediaLibrary.Updating = false;

            }
        }

        private void toolCopyAndFormat_Click(object sender, EventArgs e) {
            String destinationPath = "";
            DialogResult result = dlgOpenFolder.ShowDialog();
            if (!this.destFormatterTextbox.Text.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString())) this.destFormatterTextbox.Text += System.IO.Path.DirectorySeparatorChar;
            if (result == DialogResult.OK) {
                destinationPath = dlgOpenFolder.SelectedPath;
                startOperation(true);
                bool overWrite = false;
                bool noOverWrite = false;
                foreach (MP3File mediaFile in mediaLibrary.selectedFiles()) {
                    Application.DoEvents();
                    string finalFormat = formatFilename(mediaFile, this.formatterTextbox.Text,true);
                    System.IO.FileInfo file = new System.IO.FileInfo(mediaFile.filePath);
                    String oldFilepath = mediaFile.filePath;
                    string finalPath = getValidPath(formatFilename(mediaFile, this.destFormatterTextbox.Text,true));

                    if (!System.IO.Directory.Exists(destinationPath + System.IO.Path.DirectorySeparatorChar + finalPath))
                    {
                        System.IO.Directory.CreateDirectory(destinationPath + System.IO.Path.DirectorySeparatorChar + finalPath);
                    }
                    statusText.Text = String.Format(this.getString("mainForm.fomattingAndCopy"), mediaFile.filePath, destinationPath + System.IO.Path.DirectorySeparatorChar + finalPath + finalFormat);
                    Application.DoEvents();

                    string finalFilePath = getValidPath(destinationPath + System.IO.Path.DirectorySeparatorChar + finalPath + finalFormat);
                    bool copy = false;
                    bool alreadyExists = System.IO.File.Exists(finalFilePath);
                    if (alreadyExists & !overWrite & !noOverWrite)
                    {
                        CustomDialogResult resultOverwrite = CustomMessageBox.Show(string.Format("The file {0} already exists.\nDo you want to overwrite it?", finalFilePath), "Copy Error", CustomMessageBoxButtons.YesYesToAllNoNoToAllCancel);
                        switch (resultOverwrite)
                        {
                            case CustomDialogResult.Cancel:
                                cancelOperation();
                                break;
                            case CustomDialogResult.Yes:
                                copy = true;
                                break;
                            case CustomDialogResult.YesToAll:
                                overWrite = true;
                                break;
                            case CustomDialogResult.NoToAll:
                                noOverWrite = true;
                                break;
                            default:
                                break;
                        }
                    }
                    else
                    {
                        copy = !noOverWrite;
                    }
                    if (copy | overWrite)
                    {
                        CopyFile(file, finalFilePath);
                    }
                    
                    Application.DoEvents();
                    if (_cancelOperation) break;
                }
                endOperation();
            }
        }

        private void menuExit_Click(object sender, EventArgs e) {
            Exit();
        }
#endregion

        public void startOperation(Boolean cancelable) {
            _cancelOperation = false;
            statusProgress.Style = ProgressBarStyle.Marquee;
            if (cancelable) statusCancel.Visible = true;
        }

        public void cancelOperation() {
            _cancelOperation = true;
            endOperation();
        }

        public void endOperation() {
            statusProgress.Style = ProgressBarStyle.Continuous;
            statusCancel.Visible = false;
        }

        public void saveSettings() {
            Properties.Settings.Default.Save();
        }

        public void Exit() {
            this.Close();
        }

        #region Format and Media functions

        public void addFolder() {
            dlgOpenFolder.SelectedPath = Properties.Settings.Default.AddFolder_path;
            DialogResult result = dlgOpenFolder.ShowDialog();
            if (result == DialogResult.OK) {
                Properties.Settings.Default.AddFolder_path= dlgOpenFolder.SelectedPath;
                Properties.Settings.Default.Save();
                startOperation(true);
                addFolder( new System.IO.DirectoryInfo(dlgOpenFolder.SelectedPath));
                endOperation();
                statusText.Text = this.getString("mainForm.operationEnded");
            }
            
        }

        public void addFolder(System.IO.DirectoryInfo folder) {
            try {
                if (_cancelOperation) return;
                System.IO.FileInfo[] files = folder.GetFiles("*.mp3");
                 foreach (System.IO.FileInfo file in files) {
                     if (_cancelOperation) return;
                     Application.DoEvents();
                    addFile(file.FullName);
                }
                statusText.Text = String.Format(this.getString("mainForm.folderScanned"),folder.FullName);
            } catch (Exception e) {
                CustomMessageBox.Show(String.Format(this.getString("error.gettingFiles"), folder.FullName, Environment.NewLine, e.Message), this.getString("error.gettingFiles.title"), CustomMessageBoxButtons.OKOnly, MessageBoxIcon.Exclamation);
            }
           
            
            try {
                if (_cancelOperation) return;
                System.IO.DirectoryInfo[] directories = folder.GetDirectories();
                foreach (System.IO.DirectoryInfo dir in directories) {
                    Application.DoEvents();
                    if (_cancelOperation) return;
                    addFolder(dir);
                }
            } catch (Exception e) {
                CustomMessageBox.Show(String.Format(this.getString("error.gettingFolders"), folder.FullName, Environment.NewLine, e.Message), this.getString("error.gettingFolders.title"), CustomMessageBoxButtons.OKOnly, MessageBoxIcon.Exclamation);
            }
            
        }

        public void addFile() {
            dlgOpenFile.FileName = Properties.Settings.Default.AddFile_path;
            DialogResult result = dlgOpenFile.ShowDialog();
            if (result == DialogResult.OK) {
                Properties.Settings.Default.AddFile_path = dlgOpenFile.FileName;
                Properties.Settings.Default.Save();
                startOperation(true);
                statusText.Text =String.Format(this.getString("mainForm.addingFile"),dlgOpenFile.FileName);
                addFile(dlgOpenFile.FileName);
                endOperation();
                statusText.Text = this.getString("mainForm.operationEnded"); 
            }
            

        }

        public DataGridViewRow addFile(string filePath) {
            return mediaLibrary.addFile(filePath);
        }
        
        public String formatFilename(MP3File mediaFile, String formatString) {
            return formatFilename(mediaFile, formatString, false);
        }

        public String formatFilename(MP3File mediaFile, String formatString,bool isFolder)
        {
            if (mediaFile.UsingV1)
            {
                formatString = formatString.Replace("%title%", mediaFile.Id3v1Tag.Title);
                formatString = formatString.Replace("%album%", mediaFile.Id3v1Tag.Album);
                formatString = formatString.Replace("%artist%", mediaFile.Id3v1Tag.Artist);
                formatString = formatString.Replace("%trackNo%", mediaFile.Id3v1Tag.TrackNumber.ToString());
                formatString = formatString.Replace("%year%", mediaFile.Id3v1Tag.Year);
                formatString = formatString.Replace("%genre%", "" + mediaFile.Id3v1Tag.GenreIndex);
                formatString = formatString.Replace("%comment%", mediaFile.Id3v1Tag.Comment);
            }
            else
            {
                formatString = formatString.Replace("%title%", mediaFile.Id3v2Tag.Title);
                formatString = formatString.Replace("%album%", mediaFile.Id3v2Tag.Album);
                formatString = formatString.Replace("%artist%", mediaFile.Id3v2Tag.Artist);
                formatString = formatString.Replace("%trackNo%",mediaFile.Id3v2Tag.TrackNumber == null ? string.Empty : mediaFile.Id3v2Tag.TrackNumber.IndexOf("/") != -1 ? mediaFile.Id3v2Tag.TrackNumber.Substring(0, mediaFile.Id3v2Tag.TrackNumber.IndexOf("/")) : mediaFile.Id3v2Tag.TrackNumber);
                formatString = formatString.Replace("%year%", mediaFile.Id3v2Tag.Year);
                formatString = formatString.Replace("%genre%", mediaFile.Id3v2Tag.Genre);
                formatString = formatString.Replace("%comment%", mediaFile.Id3v2Tag.CommentsList.Count > 0 ? mediaFile.Id3v2Tag.CommentsList[0].Description : "");
            }
            formatString = trimInvalidChars(formatString, isFolder);
            return formatString;
        }

        private string trimInvalidChars(String text) {
            return trimInvalidChars(text, false);
        }

        private string trimInvalidChars(String text, bool isFolder)
        {
            text = text.Replace("?", "");
            if (!isFolder)  text = text.Replace("\\", ""); //this can be ilegal if its a file, but it's ok if its a folder
            text = text.Replace("(","");
            text = text.Replace("\"", "");
            text = text.Replace(")", "");
            text = text.Replace("/", "");
            text = text.Replace(":", "");
            text = text.Replace("*", "");
            text = text.Replace("<", "");
            text = text.Replace(">", "");
            return text;
        }

    #endregion

        private void toolAbout_Click(object sender, EventArgs e) {
            About dlgAbout = new About();
            dlgAbout.ShowDialog();
        }

        private void editToolStripMenuItem_Click(object sender, EventArgs e) {
            MediaFileWindow dlgMediaFile = new MediaFileWindow();
            if (mediaLibrary.selectedFiles().Length == 1) {
                MP3File mediaFile = mediaLibrary.selectedFiles()[0];
                if (mediaFile.UsingV1)
                {
                    dlgMediaFile.Artist = mediaFile.Id3v1Tag.Artist;
                    dlgMediaFile.Album = mediaFile.Id3v1Tag.Album;
                    dlgMediaFile.Title = mediaFile.Id3v1Tag.Title;
                    dlgMediaFile.Genre = mediaFile.Id3v1Tag.GenreIndex.ToString();
                    dlgMediaFile.TrackNo = mediaFile.Id3v1Tag.TrackNumber.ToString();
                    dlgMediaFile.Year = mediaFile.Id3v1Tag.Year;
                }else{
                    dlgMediaFile.Artist = mediaFile.Id3v2Tag.Artist;
                    dlgMediaFile.Album = mediaFile.Id3v2Tag.Album;
                    dlgMediaFile.Title = mediaFile.Id3v2Tag.Title;
                    dlgMediaFile.Genre = mediaFile.Id3v2Tag.Genre;
                    dlgMediaFile.TrackNo = mediaFile.Id3v2Tag.TrackNumber;
                    dlgMediaFile.Year = mediaFile.Id3v2Tag.Year;
                }
            }
            dlgMediaFile.Files = mediaLibrary.selectedFiles();
            DialogResult result =  dlgMediaFile.ShowDialog();
            if (result == DialogResult.OK) {
                mediaLibrary.refreshLibrary();
            }
        }

        private void mediaLibrary_DragEnter(object sender, DragEventArgs e) {
            e.Effect = DragDropEffects.All;
           
        }

        private void mediaLibrary_DragDrop(object sender, DragEventArgs e) {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            startOperation(true);
            foreach (string file in files) {
                if (file.ToLower().EndsWith(".mp3")) {
                    mediaLibrary.addFile(file);
                } else if (System.IO.Directory.Exists(file) ) {
                    addFolder(new System.IO.DirectoryInfo(file));
                }
                if (_cancelOperation) break;
            }
            endOperation();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e) {
            cancelOperation();
        }

        private String getValidPath(String path) {
            //Should check or at least return a valid path. No invalid characters (? . * ! etc) 
            return path;
        }

        private void contextualObtainInfo_Click(object sender, EventArgs e) {
            ObtainInfoFilename info = new ObtainInfoFilename();
            info.Files = mediaLibrary.selectedFiles();
            if (info.ShowDialog() == DialogResult.OK) {
                foreach (MP3File file in info.Files) {
                    mediaLibrary.refreshMedia(file);
                }
            }
            
           
        }

        private void toolEmpty_Click(object sender, EventArgs e)
        {
            mediaLibrary.clear();
        }

        private bool CopyFile(System.IO.FileInfo file, string finalPath)
        {
            bool copyDone = false;
            try
            {
                file.CopyTo(finalPath,true);
                copyDone = true;
            }
            catch (Exception ex)
            {
                CustomDialogResult errorResult = CustomMessageBox.Show(string.Format("Se ha producido el siguiente error al intentar copiar el siguiente archivo:\n{1}\n {0}", ex.Message, finalPath), "Error", CustomMessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error);
                switch (errorResult)
                {
                    case CustomDialogResult.Abort:
                        copyDone = false;
                        break;
                    case CustomDialogResult.Retry:
                        copyDone = CopyFile(file, finalPath);
                        break;
                    case CustomDialogResult.Ignore:
                        copyDone = false;
                        break;
                    default:
                        break;
                }
                copyDone = false;
            }
            return copyDone;
        }
    }
}
